#pragma once
#include <brpc/channel.h>
#include <brpc/naming_service.h>
#include <brpc/server.h>
#include <memory>
#include <httplib.h>
#include "problem.pb.h"
#include "problem.pb.cc"
#include "brpc.h"
#include "etcd_path.h"



class ProblemModule{
private:
    std::shared_ptr<brpc::Channel> _channel;
    std::shared_ptr<problem::ProblemService_Stub> _problemservice_stub;
public:
    using ptr = std::shared_ptr<ProblemModule>;
    ProblemModule(const std::string& etcd_path){
        _channel = lyt::build_etcd(etcd_path, lyt::blog_path);
        _problemservice_stub = make_shared<problem::ProblemService_Stub>(_channel.get());
    }
    void problemList(const httplib::Request &req, httplib::Response &res){
        /*
            1. 
            2. 
            3. 
        */
        problem::ProblemListRequest problemlistrequest;
        problem::ProblemListResponse problemlistresponse;
        if (!problemlistrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _problemservice_stub->ProblemList(&cntl, &problemlistrequest, &problemlistresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        problemlistresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void problemDetail(const httplib::Request &req, httplib::Response &res){
        /*
            1. 
            2. 
            3. 
        */
        problem::ProblemDetailRequest problemdetailrequest;
        problem::ProblemDetailResponse problemdetailresponse;
        if (!problemdetailrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _problemservice_stub->ProblemDetail(&cntl, &problemdetailrequest, &problemdetailresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        problemdetailresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void problemSubmit(const httplib::Request &req, httplib::Response &res){
        /*
            1. 
            2. 
            3. 
        */
        problem::SubmitRequest submitrequest;
        problem::SubmitResponse submitreqsponse;
        if (!submitrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _problemservice_stub->Submit(&cntl, &submitrequest, &submitreqsponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        submitreqsponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void problemSubmissiondetail(const httplib::Request &req, httplib::Response &res){
        /*
            1. 
            2. 
            3. 
        */
        problem::SubmissionDetailRequest submissiondetailreqest;
        problem::SubmitResponse submitresponse;
        if (!submissiondetailreqest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _problemservice_stub->SubmissionDetail(&cntl, &submissiondetailreqest, &submitresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        submitresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void problemSubmissionlist(const httplib::Request &req, httplib::Response &res){
        /*
            1. 
            2. 
            3. 
        */
        problem::SubmissionListRequest submissionlistrequest;
        problem::SubmissionListResponse submissionlistresponse;
        if (!submissionlistrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _problemservice_stub->SubmissionList(&cntl, &submissionlistrequest, &submissionlistresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        submissionlistresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void problemUserproblemlist(const httplib::Request &req, httplib::Response &res){
        /*
            1. 
            2. 
            3. 
        */
        problem::UserProblemListRequest userproblemlistrequest;
        problem::UserProblemListResponse userproblemlistresponse;
        if (!userproblemlistrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _problemservice_stub->UserProblemList(&cntl, &userproblemlistrequest, &userproblemlistresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        userproblemlistresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
};